package com.example.template;

import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Classname TemplateEngineIf
 * @Description TODO
 * @Date 2023/4/28 11:30
 * @Created by XiongXiong
 * @Author: X.I.O
 */
public class TemplateEngineIf {




    public static void main(String[] args) {
        String template = "<p>Hello, ${name}!</p>\n" +
                "<if test=\"age > 18\">You are an adult.</if>\n" +
                "<if test=\"gender == 'male' and age >= 18\">Welcome, sir!</if>\n" +
                "<if test=\"gender == 'female' and age >= 18\">Welcome, madam!</if>";
        Map<String, Object> context = new HashMap<>();
        context.put("name", "Alice");
        context.put("age", 25);
        context.put("gender", "female");
        String output = TemplateEngineIf.render(template, context);
        System.out.println(output);
    }

    private static final String VAR_PATTERN = "\\$\\{([a-zA-Z_][a-zA-Z0-9_]*)\\}";
    private static final String IF_PATTERN = "<if\\s+test=\"([^\"]*)\">(.*?)</if>";
    private static final Pattern VAR_REGEX = Pattern.compile(VAR_PATTERN);
    private static final Pattern IF_REGEX = Pattern.compile(IF_PATTERN, Pattern.DOTALL);

    // 解析模板并返回最终的文本
    public static String render(String template, Map<String, Object> context) {
        String output = renderVars(template, context);
        System.out.println(output);
        output = renderIf(output, context);
        return output;
    }

    // 渲染变量
    private static String renderVars(String template, Map<String, Object> context) {
        StringBuffer result = new StringBuffer();
        Matcher matcher = VAR_REGEX.matcher(template);

        while (matcher.find()) {
            String key = matcher.group(1);
            String value = context.getOrDefault(key, "").toString();
            matcher.appendReplacement(result, Matcher.quoteReplacement(value));
        }

        matcher.appendTail(result);
        return result.toString();
    }

    // 渲染if语句
    private static String renderIf(String template, Map<String, Object> context) {
        Matcher matcher = IF_REGEX.matcher(template);

        while (matcher.find()) {
            String conditionExpr = matcher.group(1);
            String content = matcher.group(2);
            boolean condition = evaluateCondition(conditionExpr, context);
            String replacement = condition ? content : "";
            template = template.replace(matcher.group(0), replacement);
        }

        return template;
    }

    // 计算逻辑表达式的值
    private static boolean evaluateCondition(String conditionExpr, Map<String, Object> context) {
        boolean result = true;
        String[] conditions = conditionExpr.split("\\s*(and|or)\\s*");


        for (int i = 0; i < conditions.length; i++) {
            boolean conditionValue = evaluateSingleCondition(conditions[i], context);

            if (i == 0) {
                result = conditionValue;
            } else {
                System.out.println(conditionValue+" "+conditionExpr+" 111");
                System.out.println(conditionExpr.replaceAll("\\S+", "").trim());
                String operator = conditionExpr.replaceAll("\\S+", "").trim().substring(i - 1, i);
                switch (operator) {
                    case "and":
                        result = result && conditionValue;
                        break;
                    case "or":
                        result = result || conditionValue;
                        break;
                    default:
                        break;
                }
            }
        }
        return result;
    }

    // 计算单个条件表达式的值
    private static boolean evaluateSingleCondition(String conditionExpr, Map<String, Object> context) {
        boolean result = true;
        String[] parts = conditionExpr.split("\\s+not\\s+");

        if (parts.length > 1) {
            result = !evaluateCondition(parts[1], context);
        } else {
            Matcher matcher = Pattern.compile("(.+?)\\s*(==|!=|<|>|<=|>=)\\s*(.+)").matcher(conditionExpr);

            if (matcher.matches()) {
                Object value1 = getValue(matcher.group(1), context);
                Object value2 = getValue(matcher.group(3), context);

                if (value1 != null && value2 != null) {
                    String operator = matcher.group(2);

                    switch (operator) {
                        case "==":
                            result = value1.equals(value2);
                            break;
                        case "!=":
                            result = !value1.equals(value2);
                            break;
                        case "<":
                            result = Double.parseDouble(value1.toString()) < Double.parseDouble(value2.toString());
                            break;
                        case ">":
                            result = Double.parseDouble(value1.toString()) > Double.parseDouble(value2.toString());
                            break;
                        case "<=":
                            result = Double.parseDouble(value1.toString()) <= Double.parseDouble(value2.toString());
                            break;
                        case ">=":
                            result = Double.parseDouble(value1.toString()) >= Double.parseDouble(value2.toString());
                            break;
                        default:
                            break;
                    }
                }
            }
        }
        return result;
    }

    // 获取对象中指定属性名或方法名对应的值
    private static Object getValue(String expr, Map<String, Object> context) {
        Object result = null;

        if (expr.startsWith("'") && expr.endsWith("'")) {
            result = expr.substring(1, expr.length() - 1);
        } else if (expr.matches("-?\\d+(\\.\\d+)?")) {
            result = Double.parseDouble(expr);
        } else {
            String[] parts = expr.split("\\.");

            if (parts.length == 1) {
                result = context.getOrDefault(parts[0], null);
            } else {
                Object obj = context.getOrDefault(parts[0], null);

                if (obj != null) {
                    for (int i = 1; i < parts.length; i++) {
                        obj = getPropertyValue(obj, parts[i]);
                        if (obj == null) {
                            break;
                        }
                    }
                }

                result = obj;
            }
        }

        return result;
    }

    // 获取对象中指定属性名或方法名对应的值
    private static Object getPropertyValue(Object obj, String name) {
        Object result = null;

        try {
            Class<?> clazz = obj.getClass();
            String methodName = "get" + name.substring(0, 1).toUpperCase() + name.substring(1);
            result = clazz.getMethod(methodName).invoke(obj);
        } catch (Exception e) {
            // ignore
        }

        return result;
    }


}
